home *** CD-ROM | disk | FTP | other *** search
/ SGI Freeware 1999 August / SGI Freeware 1999 August.iso / dist / fw_emacs.idb / usr / freeware / share / emacs / 19.34 / lisp / gnus-salt.el.z / gnus-salt.el
Encoding:
Text File  |  1998-10-28  |  21.1 KB  |  655 lines

  1. ;;; gnus-salt.el --- alternate summary mode interfaces for Gnus
  2. ;; Copyright (C) 1996 Free Software Foundation, Inc.
  3.  
  4. ;; Author: Lars Magne Ingebrigtsen <larsi@ifi.uio.no>
  5.  
  6. ;; This file is part of GNU Emacs.
  7.  
  8. ;; GNU Emacs is free software; you can redistribute it and/or modify
  9. ;; it under the terms of the GNU General Public License as published by
  10. ;; the Free Software Foundation; either version 2, or (at your option)
  11. ;; any later version.
  12.  
  13. ;; GNU Emacs is distributed in the hope that it will be useful,
  14. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16. ;; GNU General Public License for more details.
  17.  
  18. ;; You should have received a copy of the GNU General Public License
  19. ;; along with GNU Emacs; see the file COPYING.  If not, write to the
  20. ;; Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  21. ;; Boston, MA 02111-1307, USA.
  22.  
  23. ;;; Commentary:
  24.  
  25. ;;; Code:
  26.  
  27. (require 'gnus)
  28. (eval-when-compile (require 'cl))
  29.  
  30. ;;;
  31. ;;; gnus-pick-mode
  32. ;;;
  33.  
  34. (defvar gnus-pick-mode nil
  35.   "Minor mode for providing a pick-and-read interface in Gnus summary buffers.")
  36.  
  37. (defvar gnus-pick-display-summary nil
  38.   "*Display summary while reading.")
  39.  
  40. (defvar gnus-pick-mode-hook nil
  41.   "Hook run in summary pick mode buffers.")
  42.  
  43. ;;; Internal variables.
  44.  
  45. (defvar gnus-pick-mode-map nil)
  46.  
  47. (unless gnus-pick-mode-map
  48.   (setq gnus-pick-mode-map (make-sparse-keymap))
  49.  
  50.   (gnus-define-keys
  51.    gnus-pick-mode-map
  52.    "t" gnus-uu-mark-thread
  53.    "T" gnus-uu-unmark-thread
  54.    " " gnus-summary-mark-as-processable
  55.    "u" gnus-summary-unmark-as-processable
  56.    "U" gnus-summary-unmark-all-processable
  57.    "v" gnus-uu-mark-over
  58.    "r" gnus-uu-mark-region
  59.    "R" gnus-uu-unmark-region
  60.    "e" gnus-uu-mark-by-regexp
  61.    "E" gnus-uu-mark-by-regexp
  62.    "b" gnus-uu-mark-buffer
  63.    "B" gnus-uu-unmark-buffer
  64.    "\r" gnus-pick-start-reading))
  65.  
  66. (defun gnus-pick-make-menu-bar ()
  67.   (unless (boundp 'gnus-pick-menu)
  68.     (easy-menu-define
  69.      gnus-pick-menu gnus-pick-mode-map ""
  70.      '("Pick"
  71.        ("Pick"
  72.     ["Article" gnus-summary-mark-as-processable t]
  73.     ["Thread" gnus-uu-mark-thread t]
  74.     ["Region" gnus-uu-mark-region t]
  75.     ["Regexp" gnus-uu-mark-regexp t]
  76.     ["Buffer" gnus-uu-mark-buffer t])
  77.        ("Unpick"
  78.     ["Article" gnus-summary-unmark-as-processable t]
  79.     ["Thread" gnus-uu-unmark-thread t]
  80.     ["Region" gnus-uu-unmark-region t]
  81.     ["Regexp" gnus-uu-unmark-regexp t]
  82.     ["Buffer" gnus-uu-unmark-buffer t])
  83.        ["Start reading" gnus-pick-start-reading t]
  84.        ["Switch pick mode off" gnus-pick-mode gnus-pick-mode]))))
  85.  
  86. (defun gnus-pick-mode (&optional arg)
  87.   "Minor mode for providing a pick-and-read interface in Gnus summary buffers.
  88.  
  89. \\{gnus-pick-mode-map}"
  90.   (interactive "P")
  91.   (when (eq major-mode 'gnus-summary-mode)
  92.     (make-local-variable 'gnus-pick-mode)
  93.     (setq gnus-pick-mode 
  94.       (if (null arg) (not gnus-pick-mode)
  95.         (> (prefix-numeric-value arg) 0)))
  96.     (when gnus-pick-mode
  97.       ;; Make sure that we don't select any articles upon group entry.
  98.       (make-local-variable 'gnus-auto-select-first)
  99.       (setq gnus-auto-select-first nil)
  100.       ;; Set up the menu.
  101.       (when (and menu-bar-mode
  102.          (gnus-visual-p 'pick-menu 'menu))
  103.     (gnus-pick-make-menu-bar))
  104.       (unless (assq 'gnus-pick-mode minor-mode-alist)
  105.     (push '(gnus-pick-mode " Pick") minor-mode-alist))
  106.       (unless (assq 'gnus-pick-mode minor-mode-map-alist)
  107.     (push (cons 'gnus-pick-mode gnus-pick-mode-map)
  108.           minor-mode-map-alist))
  109.       (run-hooks 'gnus-pick-mode-hook))))
  110.  
  111. (defun gnus-pick-start-reading (&optional catch-up)
  112.   "Start reading the picked articles.
  113. If given a prefix, mark all unpicked articles as read."
  114.   (interactive "P")
  115.   (unless gnus-newsgroup-processable
  116.     (error "No articles have been picked"))
  117.   (gnus-summary-limit-to-articles nil)
  118.   (when catch-up
  119.     (gnus-summary-limit-mark-excluded-as-read))
  120.   (gnus-summary-first-unread-article)
  121.   (gnus-configure-windows (if gnus-pick-display-summary 'article 'pick) t))
  122.  
  123.  
  124. ;;;
  125. ;;; gnus-binary-mode
  126. ;;;
  127.  
  128. (defvar gnus-binary-mode nil
  129.   "Minor mode for provind a binary group interface in Gnus summary buffers.")
  130.  
  131. (defvar gnus-binary-mode-hook nil
  132.   "Hook run in summary binary mode buffers.")
  133.  
  134. (defvar gnus-binary-mode-map nil)
  135.  
  136. (unless gnus-binary-mode-map
  137.   (setq gnus-binary-mode-map (make-sparse-keymap))
  138.  
  139.   (gnus-define-keys
  140.    gnus-binary-mode-map
  141.    "g" gnus-binary-show-article))
  142.  
  143. (defun gnus-binary-make-menu-bar ()
  144.   (unless (boundp 'gnus-binary-menu)
  145.     (easy-menu-define
  146.      gnus-binary-menu gnus-binary-mode-map ""
  147.      '("Pick"
  148.        ["Switch binary mode off" gnus-binary-mode t]))))
  149.  
  150. (defun gnus-binary-mode (&optional arg)
  151.   "Minor mode for providing a binary group interface in Gnus summary buffers."
  152.   (interactive "P")
  153.   (when (eq major-mode 'gnus-summary-mode)
  154.     (make-local-variable 'gnus-binary-mode)
  155.     (setq gnus-binary-mode 
  156.       (if (null arg) (not gnus-binary-mode)
  157.         (> (prefix-numeric-value arg) 0)))
  158.     (when gnus-binary-mode
  159.       ;; Make sure that we don't select any articles upon group entry.
  160.       (make-local-variable 'gnus-auto-select-first)
  161.       (setq gnus-auto-select-first nil)
  162.       (make-local-variable 'gnus-summary-display-article-function)
  163.       (setq gnus-summary-display-article-function 'gnus-binary-display-article)
  164.       ;; Set up the menu.
  165.       (when (and menu-bar-mode
  166.          (gnus-visual-p 'binary-menu 'menu))
  167.     (gnus-binary-make-menu-bar))
  168.       (unless (assq 'gnus-binary-mode minor-mode-alist)
  169.     (push '(gnus-binary-mode " Binary") minor-mode-alist))
  170.       (unless (assq 'gnus-binary-mode minor-mode-map-alist)
  171.     (push (cons 'gnus-binary-mode gnus-binary-mode-map)
  172.           minor-mode-map-alist))
  173.       (run-hooks 'gnus-binary-mode-hook))))
  174.  
  175. (defun gnus-binary-display-article (article &optional all-header)
  176.   "Run ARTICLE through the binary decode functions."
  177.   (when (gnus-summary-goto-subject article)
  178.     (let ((gnus-view-pseudos 'automatic))
  179.       (gnus-uu-decode-uu))))
  180.  
  181. (defun gnus-binary-show-article (&optional arg)
  182.   "Bypass the binary functions and show the article."
  183.   (interactive "P")
  184.   (let (gnus-summary-display-article-function)
  185.     (gnus-summary-show-article arg)))
  186.  
  187. ;;;
  188. ;;; gnus-tree-mode
  189. ;;;
  190.  
  191. (defvar gnus-tree-line-format "%(%[%3,3n%]%)"
  192.   "Format of tree elements.")
  193.  
  194. (defvar gnus-tree-minimize-window t
  195.   "If non-nil, minimize the tree buffer window.
  196. If a number, never let the tree buffer grow taller than that number of
  197. lines.")
  198.  
  199. (defvar gnus-selected-tree-face 'modeline
  200.   "*Face used for highlighting selected articles in the thread tree.")
  201.  
  202. (defvar gnus-tree-brackets '((?\[ . ?\]) (?\( . ?\))
  203.                  (?\{ . ?\}) (?< . ?>))
  204.   "Brackets used in tree nodes.")
  205.  
  206. (defvar gnus-tree-parent-child-edges '(?- ?\\ ?|)
  207.   "Charaters used to connect parents with children.")
  208.  
  209. (defvar gnus-tree-mode-line-format "Gnus: %%b %S %Z"
  210.   "*The format specification for the tree mode line.")
  211.  
  212. (defvar gnus-generate-tree-function 'gnus-generate-vertical-tree
  213.   "*Function for generating a thread tree.
  214. Two predefined functions are available:
  215. `gnus-generate-horizontal-tree' and `gnus-generate-vertical-tree'.")
  216.  
  217. (defvar gnus-tree-mode-hook nil
  218.   "*Hook run in tree mode buffers.")
  219.  
  220. ;;; Internal variables.
  221.  
  222. (defvar gnus-tree-line-format-alist 
  223.   `((?n gnus-tmp-name ?s)
  224.     (?f gnus-tmp-from ?s)
  225.     (?N gnus-tmp-number ?d)
  226.     (?\[ gnus-tmp-open-bracket ?c)
  227.     (?\] gnus-tmp-close-bracket ?c)
  228.     (?s gnus-tmp-subject ?s)))
  229.  
  230. (defvar gnus-tree-mode-line-format-alist gnus-summary-mode-line-format-alist)
  231.  
  232. (defvar gnus-tree-mode-line-format-spec nil)
  233. (defvar gnus-tree-line-format-spec nil)
  234.  
  235. (defvar gnus-tree-node-length nil)
  236. (defvar gnus-selected-tree-overlay nil)
  237.  
  238. (defvar gnus-tree-displayed-thread nil)
  239.  
  240. (defvar gnus-tree-mode-map nil)
  241. (put 'gnus-tree-mode 'mode-class 'special)
  242.  
  243. (unless gnus-tree-mode-map
  244.   (setq gnus-tree-mode-map (make-keymap))
  245.   (suppress-keymap gnus-tree-mode-map)
  246.   (gnus-define-keys
  247.    gnus-tree-mode-map
  248.    "\r" gnus-tree-select-article
  249.    gnus-mouse-2 gnus-tree-pick-article
  250.    "\C-?" gnus-tree-read-summary-keys
  251.  
  252.    "\C-c\C-i" gnus-info-find-node)
  253.  
  254.   (substitute-key-definition
  255.    'undefined 'gnus-tree-read-summary-keys gnus-tree-mode-map))
  256.  
  257. (defun gnus-tree-make-menu-bar ()
  258.   (unless (boundp 'gnus-tree-menu)
  259.     (easy-menu-define
  260.      gnus-tree-menu gnus-tree-mode-map ""
  261.      '("Tree"
  262.        ["Select article" gnus-tree-select-article t]))))
  263.  
  264. (defun gnus-tree-mode ()
  265.   "Major mode for displaying thread trees."
  266.   (interactive)
  267.   (setq gnus-tree-mode-line-format-spec 
  268.     (gnus-parse-format gnus-tree-mode-line-format 
  269.                gnus-summary-mode-line-format-alist))
  270.   (setq gnus-tree-line-format-spec 
  271.     (gnus-parse-format gnus-tree-line-format 
  272.                gnus-tree-line-format-alist t))
  273.   (when (and menu-bar-mode
  274.          (gnus-visual-p 'tree-menu 'menu))
  275.     (gnus-tree-make-menu-bar))
  276.   (kill-all-local-variables)
  277.   (gnus-simplify-mode-line)
  278.   (setq mode-name "Tree")
  279.   (setq major-mode 'gnus-tree-mode)
  280.   (use-local-map gnus-tree-mode-map)
  281.   (buffer-disable-undo (current-buffer))
  282.   (setq buffer-read-only t)
  283.   (setq truncate-lines t)
  284.   (save-excursion
  285.     (gnus-set-work-buffer)
  286.     (gnus-tree-node-insert (make-mail-header "") nil)
  287.     (setq gnus-tree-node-length (1- (point))))
  288.   (run-hooks 'gnus-tree-mode-hook))
  289.  
  290. (defun gnus-tree-read-summary-keys (&optional arg)
  291.   "Read a summary buffer key sequence and execute it."
  292.   (interactive "P")
  293.   (let ((buf (current-buffer))
  294.     win)
  295.     (gnus-article-read-summary-keys arg nil t)
  296.     (when (setq win (get-buffer-window buf))
  297.       (select-window win)
  298.       (when gnus-selected-tree-overlay
  299.     (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
  300.       (gnus-tree-minimize))))
  301.  
  302. (defun gnus-tree-select-article (article)
  303.   "Select the article under point, if any."
  304.   (interactive (list (gnus-tree-article-number)))
  305.   (let ((buf (current-buffer)))
  306.     (when article
  307.       (save-excursion
  308.     (set-buffer gnus-summary-buffer)
  309.     (gnus-summary-goto-article article))
  310.       (select-window (get-buffer-window buf)))))
  311.  
  312. (defun gnus-tree-pick-article (e)
  313.   "Select the article under the mouse pointer."
  314.   (interactive "e")
  315.   (mouse-set-point e)
  316.   (gnus-tree-select-article (gnus-tree-article-number)))
  317.  
  318. (defun gnus-tree-article-number ()
  319.   (get-text-property (point) 'gnus-number))
  320.  
  321. (defun gnus-tree-article-region (article)
  322.   "Return a cons with BEG and END of the article region."
  323.   (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
  324.     (when pos
  325.       (cons pos (next-single-property-change pos 'gnus-number)))))
  326.  
  327. (defun gnus-tree-goto-article (article)
  328.   (let ((pos (text-property-any (point-min) (point-max) 'gnus-number article)))
  329.     (when pos
  330.       (goto-char pos))))
  331.  
  332. (defun gnus-tree-recenter ()
  333.   "Center point in the tree window."
  334.   (let ((selected (selected-window))
  335.     (tree-window (get-buffer-window gnus-tree-buffer t)))
  336.     (when tree-window
  337.       (select-window tree-window)
  338.       (when gnus-selected-tree-overlay
  339.     (goto-char (or (gnus-overlay-end gnus-selected-tree-overlay) 1)))
  340.       (let* ((top (cond ((< (window-height) 4) 0)
  341.             ((< (window-height) 7) 1)
  342.             (t 2))) 
  343.          (height (1- (window-height)))
  344.          (bottom (save-excursion (goto-char (point-max))
  345.                      (forward-line (- height))
  346.                      (point))))
  347.     ;; Set the window start to either `bottom', which is the biggest
  348.     ;; possible valid number, or the second line from the top,
  349.     ;; whichever is the least.
  350.     (set-window-start
  351.      tree-window (min bottom (save-excursion 
  352.                    (forward-line (- top)) (point)))))
  353.       (select-window selected))))
  354.  
  355. (defun gnus-get-tree-buffer ()
  356.   "Return the tree buffer properly initialized."
  357.   (save-excursion
  358.     (set-buffer (get-buffer-create gnus-tree-buffer))
  359.     (unless (eq major-mode 'gnus-tree-mode)
  360.       (gnus-add-current-to-buffer-list)
  361.       (gnus-tree-mode))
  362.     (current-buffer)))
  363.  
  364. (defun gnus-tree-minimize ()
  365.   (when (and gnus-tree-minimize-window
  366.          (not (one-window-p)))
  367.     (let ((windows 0)
  368.       tot-win-height)
  369.       (walk-windows (lambda (window) (incf windows)))
  370.       (setq tot-win-height 
  371.         (- (frame-height) 
  372.            (* window-min-height (1- windows))
  373.            2))
  374.       (let* ((window-min-height 2)
  375.          (height (count-lines (point-min) (point-max)))
  376.          (min (max (1- window-min-height) height))
  377.          (tot (if (numberp gnus-tree-minimize-window)
  378.               (min gnus-tree-minimize-window min)
  379.             min))
  380.          (win (get-buffer-window (current-buffer)))
  381.          (wh (and win (1- (window-height win)))))
  382.     (setq tot (min tot tot-win-height))
  383.     (when (and win
  384.            (not (eq tot wh)))
  385.       (let ((selected (selected-window)))
  386.         (select-window win)
  387.         (enlarge-window (- tot wh))
  388.         (select-window selected)))))))
  389.  
  390. ;;; Generating the tree.
  391.  
  392. (defun gnus-tree-node-insert (header sparse &optional adopted)
  393.   (let* ((dummy (stringp header))
  394.      (header (if (vectorp header) header
  395.            (progn
  396.              (setq header (make-mail-header "*****"))
  397.              (mail-header-set-number header 0)
  398.              (mail-header-set-lines header 0)
  399.              (mail-header-set-chars header 0)
  400.              header)))
  401.      (gnus-tmp-from (mail-header-from header))
  402.      (gnus-tmp-subject (mail-header-subject header))
  403.      (gnus-tmp-number (mail-header-number header))
  404.      (gnus-tmp-name
  405.       (cond
  406.        ((string-match "(.+)" gnus-tmp-from)
  407.         (substring gnus-tmp-from
  408.                (1+ (match-beginning 0)) (1- (match-end 0))))
  409.        ((string-match "<[^>]+> *$" gnus-tmp-from)
  410.         (let ((beg (match-beginning 0)))
  411.           (or (and (string-match "^\"[^\"]*\"" gnus-tmp-from)
  412.                (substring gnus-tmp-from (1+ (match-beginning 0))
  413.                   (1- (match-end 0))))
  414.           (substring gnus-tmp-from 0 beg))))
  415.        ((memq gnus-tmp-number sparse)
  416.         "***")
  417.        (t gnus-tmp-from)))
  418.      (gnus-tmp-open-bracket
  419.       (cond ((memq gnus-tmp-number sparse) 
  420.          (caadr gnus-tree-brackets))
  421.         (dummy (caaddr gnus-tree-brackets))
  422.         (adopted (car (nth 3 gnus-tree-brackets)))
  423.         (t (caar gnus-tree-brackets))))
  424.      (gnus-tmp-close-bracket
  425.       (cond ((memq gnus-tmp-number sparse)
  426.          (cdadr gnus-tree-brackets))
  427.         (adopted (cdr (nth 3 gnus-tree-brackets)))
  428.         (dummy
  429.          (cdaddr gnus-tree-brackets))
  430.         (t (cdar gnus-tree-brackets))))
  431.      (buffer-read-only nil)
  432.      beg end)
  433.     (gnus-add-text-properties
  434.      (setq beg (point))
  435.      (setq end (progn (eval gnus-tree-line-format-spec) (point)))
  436.      (list 'gnus-number gnus-tmp-number))
  437.     (when (or t (gnus-visual-p 'tree-highlight 'highlight))
  438.       (gnus-tree-highlight-node gnus-tmp-number beg end))))
  439.  
  440. (defun gnus-tree-highlight-node (article beg end)
  441.   "Highlight current line according to `gnus-summary-highlight'."
  442.   (let ((list gnus-summary-highlight)
  443.     face)
  444.     (save-excursion
  445.       (set-buffer gnus-summary-buffer)
  446.       (let* ((score (or (cdr (assq article gnus-newsgroup-scored))
  447.             gnus-summary-default-score 0))
  448.          (default gnus-summary-default-score)
  449.          (mark (or (gnus-summary-article-mark article) gnus-unread-mark)))
  450.     ;; Eval the cars of the lists until we find a match.
  451.     (while (and list
  452.             (not (eval (caar list))))
  453.       (setq list (cdr list)))))
  454.     (unless (eq (setq face (cdar list)) (get-text-property beg 'face))
  455.       (gnus-put-text-property 
  456.        beg end 'face 
  457.        (if (boundp face) (symbol-value face) face)))))
  458.  
  459. (defun gnus-tree-indent (level)
  460.   (insert (make-string (1- (* (1+ gnus-tree-node-length) level)) ? )))
  461.  
  462. (defvar gnus-tmp-limit)
  463. (defvar gnus-tmp-sparse)
  464. (defvar gnus-tmp-indent)
  465.  
  466. (defun gnus-generate-tree (thread)
  467.   "Generate a thread tree for THREAD."
  468.   (save-excursion
  469.     (set-buffer (gnus-get-tree-buffer))
  470.     (let ((buffer-read-only nil)
  471.       (gnus-tmp-indent 0))
  472.       (erase-buffer)
  473.       (funcall gnus-generate-tree-function thread 0)
  474.       (gnus-set-mode-line 'tree)
  475.       (goto-char (point-min))
  476.       (gnus-tree-minimize)
  477.       (gnus-tree-recenter)
  478.       (let ((selected (selected-window)))
  479.     (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
  480.       (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
  481.       (gnus-horizontal-recenter)
  482.       (select-window selected))))))
  483.  
  484. (defun gnus-generate-horizontal-tree (thread level &optional dummyp adopted)
  485.   "Generate a horizontal tree."
  486.   (let* ((dummy (stringp (car thread)))
  487.      (do (or dummy
  488.          (memq (mail-header-number (car thread)) gnus-tmp-limit)))
  489.      col beg)
  490.     (if (not do)
  491.     ;; We don't want this article.
  492.     (setq thread (cdr thread))
  493.       (if (not (bolp))
  494.       ;; Not the first article on the line, so we insert a "-".
  495.       (insert (car gnus-tree-parent-child-edges))
  496.     ;; If the level isn't zero, then we insert some indentation.
  497.     (unless (zerop level)
  498.       (gnus-tree-indent level)
  499.       (insert (cadr gnus-tree-parent-child-edges))
  500.       (setq col (- (setq beg (point)) (gnus-point-at-bol) 1))
  501.       ;; Draw "|" lines upwards.
  502.       (while (progn
  503.            (forward-line -1)
  504.            (forward-char col)
  505.            (= (following-char) ? ))
  506.         (delete-char 1)
  507.         (insert (caddr gnus-tree-parent-child-edges)))
  508.       (goto-char beg)))
  509.       (setq dummyp nil)
  510.       ;; Insert the article node.
  511.       (gnus-tree-node-insert (pop thread) gnus-tmp-sparse adopted))
  512.     (if (null thread)
  513.     ;; End of the thread, so we go to the next line.
  514.     (unless (bolp)
  515.       (insert "\n"))
  516.       ;; Recurse downwards in all children of this article.
  517.       (while thread
  518.     (gnus-generate-horizontal-tree
  519.      (pop thread) (if do (1+ level) level) 
  520.      (or dummyp dummy) dummy)))))
  521.  
  522. (defsubst gnus-tree-indent-vertical ()
  523.   (let ((len (- (* (1+ gnus-tree-node-length) gnus-tmp-indent) 
  524.         (- (point) (gnus-point-at-bol)))))
  525.     (when (> len 0)
  526.       (insert (make-string len ? )))))
  527.  
  528. (defsubst gnus-tree-forward-line (n)
  529.   (while (>= (decf n) 0)
  530.     (unless (zerop (forward-line 1))
  531.       (end-of-line)
  532.       (insert "\n")))
  533.   (end-of-line))
  534.  
  535. (defun gnus-generate-vertical-tree (thread level &optional dummyp adopted)
  536.   "Generate a vertical tree."
  537.   (let* ((dummy (stringp (car thread)))
  538.      (do (or dummy
  539.          (memq (mail-header-number (car thread)) gnus-tmp-limit)))
  540.      beg)
  541.     (if (not do)
  542.     ;; We don't want this article.
  543.     (setq thread (cdr thread))
  544.       (if (not (save-excursion (beginning-of-line) (bobp)))
  545.       ;; Not the first article on the line, so we insert a "-".
  546.       (progn
  547.         (gnus-tree-indent-vertical)
  548.         (insert (make-string (/ gnus-tree-node-length 2) ? ))
  549.         (insert (caddr gnus-tree-parent-child-edges))
  550.         (gnus-tree-forward-line 1))
  551.     ;; If the level isn't zero, then we insert some indentation.
  552.     (unless (zerop gnus-tmp-indent)
  553.       (gnus-tree-forward-line (1- (* 2 level)))
  554.       (gnus-tree-indent-vertical)
  555.       (delete-char -1)
  556.       (insert (cadr gnus-tree-parent-child-edges))
  557.       (setq beg (point))
  558.       ;; Draw "-" lines leftwards.
  559.       (while (progn
  560.            (forward-char -2)
  561.            (= (following-char) ? ))
  562.         (delete-char 1)
  563.         (insert (car gnus-tree-parent-child-edges)))
  564.       (goto-char beg)
  565.       (gnus-tree-forward-line 1)))
  566.       (setq dummyp nil)
  567.       ;; Insert the article node.
  568.       (gnus-tree-indent-vertical)
  569.       (gnus-tree-node-insert (pop thread) gnus-tmp-sparse adopted)
  570.       (gnus-tree-forward-line 1))
  571.     (if (null thread)
  572.     ;; End of the thread, so we go to the next line.
  573.     (progn
  574.       (goto-char (point-min))
  575.       (end-of-line)
  576.       (incf gnus-tmp-indent))
  577.       ;; Recurse downwards in all children of this article.
  578.       (while thread
  579.     (gnus-generate-vertical-tree
  580.      (pop thread) (if do (1+ level) level) 
  581.      (or dummyp dummy) dummy)))))
  582.  
  583. ;;; Interface functions.
  584.  
  585. (defun gnus-possibly-generate-tree (article &optional force)
  586.   "Generate the thread tree for ARTICLE if it isn't displayed already."
  587.   (when (save-excursion
  588.       (set-buffer gnus-summary-buffer)
  589.       (and gnus-use-trees
  590.            (vectorp (gnus-summary-article-header article))))
  591.     (save-excursion
  592.       (let ((top (save-excursion
  593.            (set-buffer gnus-summary-buffer)
  594.            (gnus-cut-thread
  595.             (gnus-remove-thread 
  596.              (mail-header-id 
  597.               (gnus-summary-article-header article)) t))))
  598.         (gnus-tmp-limit gnus-newsgroup-limit)
  599.         (gnus-tmp-sparse gnus-newsgroup-sparse))
  600.     (when (or force
  601.           (not (eq top gnus-tree-displayed-thread)))
  602.       (gnus-generate-tree top)
  603.       (setq gnus-tree-displayed-thread top))))))
  604.  
  605. (defun gnus-tree-open (group)
  606.   (gnus-get-tree-buffer))
  607.  
  608. (defun gnus-tree-close (group)
  609.   ;(gnus-kill-buffer gnus-tree-buffer)
  610.   )
  611.  
  612. (defun gnus-highlight-selected-tree (article)
  613.   "Highlight the selected article in the tree."
  614.   (let ((buf (current-buffer))
  615.     region)
  616.     (set-buffer gnus-tree-buffer)
  617.     (when (setq region (gnus-tree-article-region article))
  618.       (when (or (not gnus-selected-tree-overlay)
  619.         (gnus-extent-detached-p gnus-selected-tree-overlay))
  620.     ;; Create a new overlay.
  621.     (gnus-overlay-put
  622.      (setq gnus-selected-tree-overlay (gnus-make-overlay 1 2))
  623.      'face gnus-selected-tree-face))
  624.       ;; Move the overlay to the article.
  625.       (gnus-move-overlay 
  626.        gnus-selected-tree-overlay (goto-char (car region)) (cdr region))
  627.       (gnus-tree-minimize)
  628.       (gnus-tree-recenter)
  629.       (let ((selected (selected-window)))
  630.     (when (get-buffer-window (set-buffer gnus-tree-buffer) t)
  631.       (select-window (get-buffer-window (set-buffer gnus-tree-buffer) t))
  632.       (gnus-horizontal-recenter)
  633.       (select-window selected))))
  634.     ;; If we remove this save-excursion, it updates the wrong mode lines?!?
  635.     (save-excursion
  636.       (set-buffer gnus-tree-buffer)
  637.       (gnus-set-mode-line 'tree))
  638.     (set-buffer buf)))
  639.  
  640. (defun gnus-tree-highlight-article (article face)
  641.   (save-excursion
  642.     (set-buffer (gnus-get-tree-buffer))
  643.     (let (region)
  644.       (when (setq region (gnus-tree-article-region article))
  645.     (gnus-put-text-property (car region) (cdr region) 'face face)
  646.     (set-window-point 
  647.      (get-buffer-window (current-buffer) t) (cdr region))))))
  648.  
  649. ;;; Allow redefinition of functions.
  650. (gnus-ems-redefine)
  651.  
  652. (provide 'gnus-salt)
  653.  
  654. ;;; gnus-salt.el ends here
  655.